﻿namespace com.u3d.bases.loader
{
    using com.u3d.bases.debug;
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEngine;

    internal class ResLoadMgr
    {
        private BinLoadMgr binLoadMgr;
        private Dictionary<string, IList<LoadFinishBack>> errorBackList;
        private bool isLoading;
        public bool isTrace = true;
        private const int MAX_OFFET_PRIORITY = 0xffff;
        private int offetPriority = 0xffff;
        private Dictionary<string, IList<LoadFinishBack>> okBackList;
        private VerMgr verMgr;
        private IList<LoadItem> waitList;

        public ResLoadMgr(BinLoadMgr binLoadMgr, VerMgr verMgr)
        {
            this.binLoadMgr = binLoadMgr;
            this.verMgr = verMgr;
            this.waitList = new List<LoadItem>();
            this.okBackList = new Dictionary<string, IList<LoadFinishBack>>();
            this.errorBackList = new Dictionary<string, IList<LoadFinishBack>>();
        }

        private void addErrorBack(string url, LoadFinishBack errorback)
        {
            if (errorback != null)
            {
                IList<LoadFinishBack> list = !this.errorBackList.ContainsKey(url) ? null : this.errorBackList[url];
                if (list == null)
                {
                    list = new List<LoadFinishBack>();
                    this.errorBackList.Add(url, list);
                }
                list.Add(errorback);
            }
        }

        private void addFinishBack(string url, LoadFinishBack callback)
        {
            if (callback != null)
            {
                IList<LoadFinishBack> list = !this.okBackList.ContainsKey(url) ? null : this.okBackList[url];
                if (list == null)
                {
                    list = new List<LoadFinishBack>();
                    this.okBackList.Add(url, list);
                }
                list.Add(callback);
            }
        }

        public void addTask(string url, int resType, LoadFinishBack callback = null, System.Type types = null, int priority = 0, LoadFinishBack errorback = null)
        {
            if (this.okBackList.ContainsKey(url))
            {
                this.addFinishBack(url, callback);
            }
            else if (ResPool.instance.hasLoadedRes(url))
            {
                this.callFinishBack(url);
                this.remove(url, this.okBackList);
                if (callback != null)
                {
                    callback(url, null);
                }
            }
            else
            {
                LoadItem item = new LoadItem {
                    url = url,
                    types = types,
                    resType = resType,
                    priority = (priority * 0xffff) + this.offetPriority
                };
                this.offetPriority--;
                this.waitList.Add(item);
                if (!this.isLoading)
                {
                    this.loadNext();
                }
            }
        }

        private void callErrorBack(string url)
        {
            IList<LoadFinishBack> list = !this.errorBackList.ContainsKey(url) ? null : this.errorBackList[url];
            if (list != null)
            {
                IEnumerator<LoadFinishBack> enumerator = list.GetEnumerator();
                try
                {
                    while (enumerator.MoveNext())
                    {
                        LoadFinishBack current = enumerator.Current;
                        current(url, null);
                    }
                }
                finally
                {
                    if (enumerator == null)
                    {
                    }
                    enumerator.Dispose();
                }
            }
        }

        private void callFinishBack(string url)
        {
            IList<LoadFinishBack> list = !this.okBackList.ContainsKey(url) ? null : this.okBackList[url];
            if (list != null)
            {
                IEnumerator<LoadFinishBack> enumerator = list.GetEnumerator();
                try
                {
                    while (enumerator.MoveNext())
                    {
                        LoadFinishBack current = enumerator.Current;
                        current(url, null);
                    }
                }
                finally
                {
                    if (enumerator == null)
                    {
                    }
                    enumerator.Dispose();
                }
            }
        }

        private void loadNext()
        {
            if (this.waitList.Count < 1)
            {
                this.offetPriority = 0xffff;
                this.isLoading = false;
                if (this.isTrace)
                {
                    Log.info(this, "-loadNext() 加载器已空闲！");
                }
            }
            else
            {
                this.isLoading = true;
                LoadItem item = this.waitList[0];
                string path = this.verMgr.getLoadUrl(item.url);
                if (this.isTrace)
                {
                    Log.info(this, "-loadNext() url:" + path + " 加载开始！");
                }
                UnityEngine.Object data = (item.types == null) ? Resources.Load(path) : Resources.Load(path, item.types);
                ResPool.instance.addLoadedRes(item.url, data);
                this.callFinishBack(item.url);
                this.remove(item.url, this.okBackList);
                this.loadNext();
            }
        }

        private void remove(string url, Dictionary<string, IList<LoadFinishBack>> dict)
        {
            IList<LoadFinishBack> list = !dict.ContainsKey(url) ? null : dict[url];
            if (list != null)
            {
                dict.Remove(url);
                list.Clear();
                list = null;
            }
        }
    }
}

